package com.example.demo.service.imply;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.exception.MyUncheckedException;
import com.example.demo.mapper.ExamFileMapper;
import com.example.demo.mapper.ExamPaperFileMapper;
import com.example.demo.mapper.ExamPaperMapper;
import com.example.demo.mapper.SubjectMapper;
import com.example.demo.pojo.tree.TreeExamFile;
import com.example.demo.pojo.tree.TreeSubjectFile;
import com.example.demo.pojo.dto.ExamFileDTO;
import com.example.demo.pojo.entity.*;
import com.example.demo.pojo.query.ExamQuery;
import com.example.demo.pojo.vo.ExamFileShowVO;
import com.example.demo.pojo.vo.ExamVO;
import com.example.demo.pojo.vo.SubjectFileShowVO;
import com.example.demo.service.IExamFileService;
import com.example.demo.utils.UnitTreeSolveData;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author fjh
 */
@Service
@RequiredArgsConstructor
public class IExamFileServiceImply extends ServiceImpl<ExamFileMapper, ExamFile> implements IExamFileService {
    private final SubjectMapper subjectMapper;
    private final ExamFileMapper examFileMapper;
    private final ExamPaperFileMapper examPaperFileMapper;
    private final ExamPaperMapper examPaperMapper;
    /**
     * 递归的方法不断便利树
     * @author: fjh
    **/
    TreeExamFile initTreeExamFile(ExamFile nodeExamFile, List<Integer> needIdList) {
        if (nodeExamFile == null) {
            return null;
        }
        TreeExamFile tempTreeExamFile = new TreeExamFile();
        tempTreeExamFile.setExamFile(nodeExamFile);
        //查找这个节点下的所有子节点
        String childNodeId = nodeExamFile.getNodeId();
        QueryWrapper<ExamFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("node_id", childNodeId);
        queryWrapper.eq("level", nodeExamFile.getLevel() + 1);
        List<ExamFile> childrenList = examFileMapper.selectList(queryWrapper);
        for (int i = 0; i < childrenList.size(); i++) {
            if (needIdList.contains(childrenList.get(i).getId())) {
                TreeExamFile tempTree = initTreeExamFile(childrenList.get(i), needIdList);
                if (tempTree != null) {
                    tempTreeExamFile.addChild(tempTree);
                }
            }
        }
        return tempTreeExamFile;
    }
    /**
     * 递归构建树
     * @author: fjh
    **/
    List<ExamFileShowVO> solveFileExamShowVO(List<TreeExamFile> children) {
        if (children == null) {
            return null;
        }
        List<ExamFileShowVO> result = new ArrayList<>();
        for (int i = 0; i < children.size(); i++) {
            TreeExamFile treeExamFile = children.get(i);
            ExamFile ExamFile = treeExamFile.getExamFile();
            ExamFileShowVO ExamFileShowVO = new ExamFileShowVO();
            ExamFileShowVO.initExamFile(ExamFile);
            List<ExamFileShowVO> solveResult = solveFileExamShowVO(treeExamFile.getChildren());
            ExamFileShowVO.setExamFileList(solveResult);
            result.add(ExamFileShowVO);
        }
        return result;
    }
    /**
     * 根据根节点打包成树然后返回
     * @author: fjh
     * @param:
     * @return:
    **/
    List<ExamFileShowVO> completeExamVOList(ExamFile rootExamFile, List<Integer> needIdList) {
        List<ExamFileShowVO> result = new ArrayList<>();
        TreeExamFile treeExamFile = initTreeExamFile(rootExamFile, needIdList);
        ExamFileShowVO examFileShowVO = new ExamFileShowVO();
        examFileShowVO.initExamFile(rootExamFile);
        List<ExamFileShowVO> solveResult = solveFileExamShowVO(treeExamFile.getChildren());
        examFileShowVO.setExamFileList(solveResult);
        for (int i = 0; i < solveResult.size(); i++) {
            result.add(solveResult.get(i));
        }
        return result;
    }
    /**
     * 初始化文件列表，以树的形式
     * @author: fjh
     * @param: subjectId:学科的id
     * @return:
    **/
    @Override
    public List<ExamFileShowVO> initFile(int subjectId) {
        Subject subject=subjectMapper.selectById(subjectId);
        int examFileId=subject.getExamFileId();
        ExamFile rootExamFile=examFileMapper.selectById(examFileId);
        if(rootExamFile!=null){
            QueryWrapper<ExamFile>queryWrapper=new QueryWrapper<>();
            queryWrapper.likeRight("node_id",examFileId+"-");
            List<Integer>needIdList=examFileMapper.selectList(queryWrapper).stream().map(ExamFile::getId).collect(Collectors.toList());
            List<ExamFileShowVO>completeList=completeExamVOList(rootExamFile,needIdList);
            ExamFileShowVO result=new ExamFileShowVO();
            result.initExamFile(rootExamFile);
            result.setExamFileList(completeList);
            List<ExamFileShowVO>listResult=new ArrayList<>();
            listResult.add(result);
            return listResult;
        }
        return null;
    }
    /**
     * 根据条件进行文件和卷子的打包返回。
     * @author: fjh
     * @param: examQuery:查询条件
     * @return: List<ExamVO>展示数据列表
    **/
    @Override
    public List<ExamVO> filterExam(ExamQuery examQuery) {
        if(examQuery.getExamPaperName()==null){
            examQuery.setExamPaperName("");
        }
        System.out.println("卷子过滤器");
        System.out.println(examQuery);
        System.out.println(examQuery.getExamPaperName()==null);
        System.out.println(examQuery.getExamPaperName().isEmpty());
        QueryWrapper<ExamPaperFile>fileQueryWrapper=new QueryWrapper<>();
        fileQueryWrapper.eq("exam_file_id",examQuery.getFileId());
        List<Integer>examPaperIdList=examPaperFileMapper.selectList(fileQueryWrapper).stream()
                .map(ExamPaperFile::getExamPaperId)
                .collect(Collectors.toList());
        List<ExamVO>needExams=new ArrayList<>();
        ExamFile examFile=examFileMapper.selectById(examQuery.getFileId());
        //获取试卷
        if(!examPaperIdList.isEmpty()){
            String examPaperName=examQuery.getExamPaperName();
            List<ExamPaper>allExamPaper=examPaperMapper.selectBatchIds(examPaperIdList);
            for(ExamPaper examPaperFor:allExamPaper){
                if(!examPaperName.isEmpty()&&examPaperFor.getExamPaperName().contains(examPaperName)){
                    ExamVO examVO=new ExamVO();
                    examVO.initExamFile(examFile);
                    examVO.initExamPaper(examPaperFor);
                    needExams.add(examVO);
                }
                else if(examPaperName.isEmpty()){
                    ExamVO examVO=new ExamVO();
                    examVO.initExamFile(examFile);
                    examVO.initExamPaper(examPaperFor);
                    needExams.add(examVO);
                }
            }
        }
        //获取试卷文件
        if(examQuery.getFileFlag()==1){
            System.out.println("进入到选取试卷文件");
            int level=examFile.getLevel();
            String nodeId=examFile.getNodeId();
            QueryWrapper<ExamFile>examFileQueryWrapper=new QueryWrapper<>();
            examFileQueryWrapper.eq("level",level+1);
            examFileQueryWrapper.likeRight("node_id",nodeId);
            List<ExamFile>childrenExamFiles=examFileMapper.selectList(examFileQueryWrapper);
            for(ExamFile childrenExamFile:childrenExamFiles){
                ExamVO examVO=new ExamVO();
                examVO.initExamFile(childrenExamFile);
                needExams.add(0,examVO);
            }
        }
        return needExams;
    }
    /**
     * 从某个节点开始获得这个节点的所有子节点
     * @author: fjh
     * @param: examFileId:当前遍历的节点id
     * @param: idList: 过程中储存节点的list
    **/
    //辅助函数--构建中左右树
    void createTreeExamFile(int examFileId,List<Integer>idList){
        idList.add(examFileId);
        ExamFile examFile=examFileMapper.selectById(examFileId);
        String nodeId=examFile.getNodeId();
        int level=examFile.getLevel();
        QueryWrapper<ExamFile>queryWrapper=new QueryWrapper<>();
        queryWrapper.likeRight("node_id",nodeId);
        queryWrapper.eq("level",level+1);
        List<ExamFile>examFileList=examFileMapper.selectList(queryWrapper);
        for (ExamFile file : examFileList) {
            createTreeExamFile(file.getId(), idList);
        }
    }
    /**
     * 删除文件
     * @author: fjh
     * @param: 被删除的文件ID
    **/
    void solveDeletePaperExamFile(int examFileId){
        QueryWrapper<ExamPaperFile>queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("exam_file_id",examFileId);
        List<ExamPaperFile> examPaperFileList=examPaperFileMapper.selectList(queryWrapper);
        List<Integer>idList=examPaperFileList.stream().map(ExamPaperFile::getId).collect(Collectors.toList());
        if(!idList.isEmpty()){
            examFileMapper.deleteById(examFileId);
        }
    }
    /**
     * 将文件复制到另一个文件夹下，同时携带文件下的卷子一同转移
     * @author: fjh
     * @param: examFileId:被操作的文件ID
     * @param: goalExamFile:目标文件
     * @return: copyExamFile：复制后获得的新文件
    **/
    ExamFile solveCopyExamFile(int examFileId,ExamFile goalExamFile){
        ExamFile solveExamFile=examFileMapper.selectById(examFileId);
        //查找选中文件下的卷子
        QueryWrapper<ExamPaperFile>queryExamPaperFileWrapper=new QueryWrapper<>();
        queryExamPaperFileWrapper.eq("exam_file_id",examFileId);
        List<ExamPaperFile>examPaperFileList=examPaperFileMapper.selectList(queryExamPaperFileWrapper);
        //构建新的文件后将题目也转移
        ExamFile copyExamFile=new ExamFile();
        copyExamFile.initExamFile(solveExamFile);
        examFileMapper.insert(copyExamFile);
        int newId=copyExamFile.getId();
        String newNode=goalExamFile.getNodeId()+newId+"-";
        int newLevel=goalExamFile.getLevel()+1;
        UpdateWrapper<ExamFile>updateWrapper=new UpdateWrapper<>();
        updateWrapper.eq("id",newId);
        copyExamFile.setLevel(newLevel);
        copyExamFile.setNodeId(newNode);
        examFileMapper.update(copyExamFile,updateWrapper);
        //执行题目的复制
        int newExamFileId=copyExamFile.getId();
        for(ExamPaperFile examPaperFile:examPaperFileList){
            examPaperFile.setExamFileId(newExamFileId);
            ExamPaperFile insert=new ExamPaperFile();
            insert.copyExamPaperFile(examPaperFile);
            examPaperFileMapper.insert(insert);
        }
        return copyExamFile;
    }
    /**
     * 移动文件--更改被移动文件的层级和父节点，不需要改变其与卷子间的关系
     * @author: fjh
     * @param:
     * @return:
    **/
    void solveShitExamFile(ExamFile solveExamFile,ExamFile goalExamFile,int presentLevel){
        String parentNodeId=goalExamFile.getNodeId();
        int solveExamFileId=solveExamFile.getId();
        String solveNodeId=solveExamFile.getNodeId();
        UnitTreeSolveData unitTreeSolve=new UnitTreeSolveData();
        QueryWrapper<ExamFile>queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("id",solveExamFileId);
        //更改当前文件夹的位置
        String contactNodeId=unitTreeSolve.spiltNodeIdForChildren(solveNodeId,presentLevel);
        String newNodeId=parentNodeId+contactNodeId;
        int newLevel=unitTreeSolve.getLevel(newNodeId);
        solveExamFile.setNodeId(newNodeId);
        solveExamFile.setLevel(newLevel);
        UpdateWrapper<ExamFile>updateFileWrapper=new UpdateWrapper<>();
        updateFileWrapper.eq("id",solveExamFile.getId());
        examFileMapper.update(solveExamFile,updateFileWrapper);
    }
    /**
     * 添加文件
     * @author: fjh
     * @param: examFileDTO:前端传入的添加信息
     * @return: int 添加成功的个数
    **/
    @Override
    public int addFile(ExamFileDTO examFileDTO) {
        if(examFileDTO!=null){
            int fileId=examFileDTO.getFileId();
            ExamFile pexamFile=examFileMapper.selectById(fileId);
            ExamFile cexamFile=new ExamFile();
            if(pexamFile!=null){
                cexamFile.setFileName(examFileDTO.getFileName());
                cexamFile.setLevel(pexamFile.getLevel()+1);
                cexamFile.setParentId(pexamFile.getId());
                cexamFile.setCreateUser(examFileDTO.getCreateUser());
                examFileMapper.insert(cexamFile);
                int examFileId=cexamFile.getId();
                String nodeId=pexamFile.getNodeId();
                String newNodeId=nodeId+String.valueOf(examFileId)+"-";
                cexamFile.setNodeId(newNodeId);
                UpdateWrapper<ExamFile>updateWrapper=new UpdateWrapper<>();
                updateWrapper.eq("id",cexamFile.getId());
                if(examFileMapper.update(cexamFile,updateWrapper)>0){
                    return 1;
                }else{
                    return 0;
                }
            }
        }
        return 0;
    }
    /**
     * 队文件信息进行更新
     * @author: fjh
     * @param: examFileDTO:前端传入的更新信息
     * @return: int update的成功更新个数
    **/
    @Override
    public int updateFile(ExamFileDTO examFileDTO) {
        int examFileId=examFileDTO.getFileId();
        ExamFile examFile=examFileMapper.selectById(examFileId);
        if(examFileDTO.getCreateUser()!=null&&!examFile.getCreateUser().isEmpty()){
            examFile.setCreateUser(examFileDTO.getCreateUser());
        }
        if(examFileDTO.getFileName()!=null&&!examFileDTO.getFileName().isEmpty()){
            examFile.setFileName(examFileDTO.getFileName());
        }
        UpdateWrapper<ExamFile>updateWrapper=new UpdateWrapper<>();
        updateWrapper.eq("id",examFileId);
        return examFileMapper.update(examFile,updateWrapper);
    }
    /**
     * 根据文件夹id删除
     * @author: fjh
     * @param: fileId: 删除的文件ID
     * @return: boolean 是否成功删除
    **/
    @Override
    public boolean deleteFile(int fileId) throws MyUncheckedException {
        QueryWrapper<Subject>queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("file_id",fileId);
        if(!subjectMapper.selectObjs(queryWrapper).isEmpty()){
            throw new MyUncheckedException("无法删除根目录");
        }
        //查询文件夹下的所有子文件夹
        List<Integer>treeIdList=new ArrayList<>();
        createTreeExamFile(fileId,treeIdList);
        for(Integer examId:treeIdList){
            solveDeletePaperExamFile(examId);
            examFileMapper.deleteById(examId);
        }
        return true;
    }
    /**
     * 将文件从examFileId文件下复制到goalExam下
     * 仿照学科文件的操作--SubjectFileService
     * @author: fjh
     * @param: examFileId:被复制的文件id
     * @param: goalExamFileId: 复制文件的目标文件id
     * @return: 文件复制后的新信息
    **/
    @Override
    public ExamFile copyExamFile(int examFileId, int goalExamFileId) {
        ExamFile examFile=examFileMapper.selectById(examFileId);
        ExamFile goalExamFile=examFileMapper.selectById(goalExamFileId);
        List<Integer>fileIdList=new ArrayList<>();
        //获取复制的文件下的所有子文件id
        createTreeExamFile(examFileId,fileIdList);
        //处理
        HashMap<Integer,Integer>changeIdMap=new HashMap<>();
        HashMap<Integer,ExamFile>changeExamFileMap=new HashMap<>();
        ExamFile parentExamFile=goalExamFile;
        ExamFile preNewExamFile=goalExamFile;
        ExamFile preOldExamFile=goalExamFile;
        ExamFile presentExamFile=preNewExamFile;
        int presentLevel;
        int preLevel=0;
        int parentLevel=0;
        int flag=1;
        for(int i:fileIdList){
            presentExamFile=examFileMapper.selectById(i);
            presentLevel=presentExamFile.getLevel();
            if(flag==1){
                preLevel=presentLevel;
                parentLevel=parentExamFile.getLevel();
                preOldExamFile=presentExamFile;
                preNewExamFile=solveCopyExamFile(i,parentExamFile);
                parentExamFile=presentExamFile;
                flag=0;
                continue;
            }
            if(preLevel<presentLevel){
                int oldId=preOldExamFile.getId();
                int newId=preNewExamFile.getId();
                changeIdMap.put(oldId,newId);
                changeExamFileMap.put(newId,preNewExamFile);
                parentExamFile=preNewExamFile;
                preLevel=presentLevel;
                preOldExamFile=presentExamFile;
                preNewExamFile=solveCopyExamFile(i,parentExamFile);
                continue;
            }else if(preLevel==presentLevel){
                preLevel=presentLevel;
                preOldExamFile=presentExamFile;
                preNewExamFile=solveCopyExamFile(i,presentExamFile);
            }else if(presentLevel<preLevel){
                int presentParentId=presentExamFile.getParentId();
                parentExamFile=changeExamFileMap.get(changeIdMap.get(presentParentId));
                preLevel=presentLevel;
                preOldExamFile=presentExamFile;
                preNewExamFile=solveCopyExamFile(i,parentExamFile);
            }
        }
        return null;
    }
    /**
     *
     * @author: fjh
     * @param: examFileId：被移动的文件
     * @param: goalExamFileId: 目标目录
     * @return: ExamFile 移动后的文件信息
    **/
    @Override
    public ExamFile shiftSubjectFile(int examFileId, int goalExamFileId) {
        ExamFile examFile=examFileMapper.selectById(examFileId);
        ExamFile goalExamFile=examFileMapper.selectById(goalExamFileId);
        int presentLevel=examFile.getLevel();
        //获取相关文件
        QueryWrapper<ExamFile>queryWrapper=new QueryWrapper<>();
        String nodeId=examFile.getNodeId();
        queryWrapper.likeRight("node_id",nodeId);
        List<ExamFile>examFileList=examFileMapper.selectList(queryWrapper);
        for(ExamFile examFile1For:examFileList){
            solveShitExamFile(examFile1For,goalExamFile,presentLevel);
        }
        return examFile;
    }
    /**
     * 查找文件
     * @author: fjh
    **/
    @Override
    public ExamFile searchById(int fileId) {
        return examFileMapper.selectById(fileId);
    }
}
